#!python
# 
# Base scons build file for pyopensg.
#
import sys, os, re, string, copy
pj = os.path.join

try:
   import wing.wingdbstub       # stuff for debugging
except:
   print '[WRN] Unable to load wing debugging extensions'

# Auto extend path for scons-addons
try:
   import SConsAddons.Util
except:
   sys.path.insert(0,pj('Tools','scons-addons','src'))
   import SConsAddons.Util
print "Using SConsAddons from: ", os.path.dirname(SConsAddons.Util.__file__)

import SCons.Util
import SConsAddons.Options as sca_opts
import SConsAddons.Options.Pyste
import SConsAddons.Options.Boost
import SConsAddons.Options.OpenSG2
import SConsAddons.Util as sca_util      # Get the utils
import SConsAddons.Variants as sca_variants
from SConsAddons.EnvironmentBuilder import EnvironmentBuilder
GetPlatform = SConsAddons.Util.GetPlatform
Export('GetPlatform')

platform = GetPlatform()

# Setup base scons options and settings
EnsureSConsVersion(0,96)
SetOption('max_drift',30)                  # 30 second drift on MD5 Files
SetOption('implicit_cache',1)
SConsignFile('.sconsign.' + platform)      # Store all .sconsign stuff in single file

# ---- Helpers --------- #
def registerGchBuilder(env):
   """ GCC pre-compiled headers.
   
   #osg_pymod_env.Append(CPPFLAGS=["-H",'-Winvalid-pch'])
   #osg_pymod_env.Append(CPPFLAGS=['-Winvalid-pch'])
   #main_pch = osg_pymod_env.Gch(source='osgmodule_mainheader.h')
   """
   gch_header_extensions = [".h",]
   
   env['GCHFROMHCOM'] = ('$CXX -x c++ -c -o ${TARGETS[0]} $SHCXXFLAGS $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCE')
   
   gchBld = Builder(action={}, prefix={}, suffix={})
   for h in gch_header_extensions:
      gchBld.add_action(h, '$GCHFROMHCOM')
      gchBld.prefix[h] = ''
      gchBld.suffix[h] = h+'.gch'
   
   env['BUILDERS']['Gch'] = gchBld

if platform == "win32":
   # XXX: Temp hack to get msvs version setting
   if ARGUMENTS.has_key("MSVS_VERSION"):
      # Python extension modules can only be built using Visual C++ 7.1 or
      # 9.0.
      msvs_ver = ARGUMENTS["MSVS_VERSION"]
      if msvs_ver not in ("7.1", "9.0"):
         print "Cannot build Python extensions using MSVS version %s" % \
                  msvs_ver
         sys.exit(1)

      python_ver = sys.version[:3]
      if msvs_ver == "7.1" and python_ver not in ("2.4", "2.5"):
         print "Python 2.4 or 2.5 must be used with Visual C++ 7.1"
         sys.exit(1)
      elif msvs_ver == "9.0" and python_ver not in ("2.6"):
         print "Python 2.6 must be used with Visual C++ 9.0"
         sys.exit(1)

      common_env = Environment(MSVS_VERSION = msvs_ver)
      # Use the following line instead of the preceding when building with
      # Visual C++ 9.0. SCons does not know how to find the VC++ 9.0 paths.
      #common_env = Environment(MSVS_VERSION = msvs_ver, ENV = os.environ)

      if msvs_ver >= "9.0":
         common_env['SHLINKCOM'] = \
            [common_env['SHLINKCOM'],
             'mt.exe -manifest ${TARGET}.manifest -outputresource:$TARGET;2']
   else:
      common_env = Environment()
else:
   common_env = Environment(ENV = os.environ)

common_env["CONFIGUREDIR"] = '.sconf_temp_' + platform + '.' + common_env.subst('$CXX')
common_env["CONFIGURELOG"] = 'sconf.log_' + platform + '.' + common_env.subst('$CXX')

# ###############################
# Set up the build tree
# ###############################
unspecified_prefix = "use-instlinks"
buildDir           = "build." + platform + '.' + common_env.subst('$CXX')
option_filename    = "config.cache." + platform + '.' + common_env.subst('$CXX')

if common_env.has_key("MSVS"):
   msvs_version = common_env["MSVS"]["VERSION"]
   common_env["CONFIGUREDIR"] += "." + msvs_version
   common_env["CONFIGURELOG"] += "." + msvs_version
   buildDir                   += "." + msvs_version
   option_filename            += "." + msvs_version

# --- Create VARIANT and BUILDER --- #
variant_helper = sca_variants.VariantsHelper()
base_bldr = EnvironmentBuilder()

# Disable debug on windows since we only want things with release run-time
if platform == "win32":
   variant_helper.variants["type"][0].remove("debugrt")
   common_env.Append(CCFLAGS=["/Zm1200"])
elif platform == "darwin":
   os_major = os.uname()[2][0] 

   common_env.Append(CCFLAGS = ["-no-cpp-precomp"])
   common_env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle')
   common_env['SHLIBSUFFIX'] = ".so"

   # Only use the following options on Mac OS X 10.4 (Darwin 8) and older.
   if os_major < '9':
      common_env.Append(CCFLAGS = ["-fno-common"])
      common_env.Append(SHLINKFLAGS = ["-m"])

# Disable libtype since everything will be shared lib
if variant_helper.variants.has_key("libtype"):
   del variant_helper.variants["libtype"]
   
# ---------- Options ------------ #
opts = sca_opts.Options(files = [option_filename, 'options.custom'], 
                                   args= ARGUMENTS);
pyste_options = sca_opts.Pyste.Pyste("pyste","0.9.26", required=False)
use_version = True
boost_options = sca_opts.Boost.Boost("boost","1.31.1",
				     useVersion= use_version,
				     preferDynamic=True,
				     autoLink=True,
                                     libs = ['python',],
                                     required=True)
opensg_options = sca_opts.OpenSG2.OpenSG2("opensg","2.0", required=True)
distcc_option = sca_opts.BoolOption("enable_distcc", 
      "Enable use of distcc during build. (distcc must be in your path)", False)
vis_option = sca_opts.BoolOption("enable_visibility", 
      "Enable visibility flags when using g++.", True)


opts.Add('prefix', 'Installation prefix', unspecified_prefix)
opts.AddOption(sca_opts.SeparatorOption("\nPackage Options"))
opts.AddOption( opensg_options )
opts.AddOption( boost_options )
opts.AddOption( pyste_options )
opts.AddOption( distcc_option )
opts.AddOption( vis_option )
base_bldr.addOptions(opts)
variant_helper.addOptions(opts)

Export('opts', 'opensg_options', 'boost_options', 'pyste_options', 'vis_option')

help_text =  """----- PyOpenSG Build system ---
%s
Targets:
   install - Install PyOpenSG.
   type 'scons' to just build the project
"""%opts.GenerateHelpText(common_env)

# Debug option settings
if 0:
   print "---- boost settings ---"
   boost_options.dumpSettings()
   print "---- OpenSG settings ---"
   opensg_options.dumpSettings()

# ----- Package setup ------------ #
# Only do this if we aren't just outputing help text
if not SConsAddons.Util.hasHelpFlag():
   opts.Process(common_env)
   try:
      opts.Save(option_filename, common_env)
   except LookupError, le:
      pass
   
   # -- Common builder settings
   variant_helper.readOptions(common_env)
   base_bldr.readOptions(common_env)
   base_bldr.disableWarnings()         # Can't do this until after read options so we get defaults
  
   # Apply any common package options
   # Update environment for boost options
   if boost_options.isAvailable():
      boost_options.apply(common_env)    
     
   # If defaulting to instlinks prefix:
   #  - Use symlinks
   #  - Manually set the used prefix to the instlinks of the build dir
   if common_env['prefix'] == unspecified_prefix:
      if hasattr(os,'symlink'):
         common_env['INSTALL'] = sca_util.symlinkInstallFunc
      common_env['prefix'] = pj( Dir('.').get_abspath(), buildDir, 'instlinks')
   
   if common_env["enable_distcc"] and WhereIs("distcc"):
      common_env.Prepend(CXX = "distcc ", CC = "distcc ")

#   # Figure out where to put the site-packages subdirectory. On Windows, the
#   # Python installation puts the version information at the root directory
#   # (e.g., C:\Python24).
#   if platform == 'win32':
#      python_mod_subdir = pj('site-packages')
#   # On other platforms, the version information goes into the subdirectory of
#   # lib under the Python installation root (e.g., /usr/lib/python2.4).
#   else:
#      python_mod_subdir = pj('python' + sys.version[:3], 'site-packages')
   python_mod_subdir = pj('python' + sys.version[:3], 'site-packages')

   # --- Setup Installation Paths --- #
   # Setup a map with the paths that we will install everything to
   # - Note: this is used throughout the build to keep things consistent
   base_paths = {}
   base_paths['base']       = common_env['prefix']
   base_paths['lib']        = pj(base_paths['base'],'lib')
   base_paths['python_lib'] = pj(base_paths['lib'], python_mod_subdir)
   base_paths['include']    = pj(base_paths['base'],'include')
   base_paths['share']      = pj(base_paths['base'],'share','pyopensg')
   base_paths['app_base']   = pj(base_paths['share'],'apps')
   base_paths['test_base']  = pj(base_paths['share'],'test')   
   
   print "Using prefix: ", base_paths["base"]
   print "  types: ",    variant_helper.variants["type"] 
   print "  archs: ",    variant_helper.variants["arch"] 
   
   # --- FOR EACH VARIANT --- #
   for combo in variant_helper.iterate(locals(), base_bldr, common_env):
      print "   Processing combo: ", ", ".join(['%s:%s'%(i[0],i[1]) for i in combo.iteritems()])      
      
      inst_paths = copy.copy(base_paths)
      # If this is an x64 build on a non-Windows platform , then put
      # non-optimized builds of the extension module in a different directory.
      if "x64" == combo["arch"] and platform != 'win32':
         inst_paths['python_lib'] = pj(inst_paths['lib'] + '64',
                                       python_mod_subdir)

      # Enable structured exception handling for non-optimized builds. The
      # idea here is to allow Windows runtime errors that are converted to C++
      # exceptions to be handled in such a way that the debugger can be used
      # effectively to track down the problem. We do not do this for optimized
      # builds because switching from /EHsc to /EHa results in performance
      # degredation.
      base_bldr.enableStructuredExceptions("optimized" != combo["type"])

      # If debug version, put in a debug subdir
      if "optimized" != combo["type"]:
         inst_paths["python_lib"] = pj(inst_paths["python_lib"],combo["type"])
         # When building debug on Windows it appears that we can't link incrementally.
         if platform == "win32":
            build_env.Append(SHLINKFLAGS=["/INCREMENTAL:NO"])

      Export('build_env','inst_paths','opts','variant_pass','combo')      

      full_build_dir = pj(buildDir,combo_dir)         
      SConscript(dirs=['src'], build_dir=full_build_dir, duplicate=0)
   
   # close off build
   common_env.Alias('install', base_paths['base'])
  
# --------- Finish up ------------ #
Default(".");

Help(help_text);

# end
